/*
 * --------------------
 * Company					: LUOYANG GINGKO TECHNOLOGY CO.,LTD.
 * BBS						: http://www.eeschool.org
 * --------------------
 * Project Name			: USART
 * Module Name				: TXD_RXD_Ctrl
 * Description				: The codes of "TXD_RXD_Ctrl"
 * --------------------
 * Tool Versions			: Quartus II 13.1
 * Target Device			: Cyclone IV E  EP4CE10F17C8
 * --------------------
 * Engineer					: xiaorenwu
 * Revision					: V0.0
 * Created Date			: 2016-04-06
 * --------------------
 * Engineer					:
 * Revision					:
 * Modified Date			:
 * --------------------
 * Additional Comments	:
 *
 * --------------------
 */

//--------------------Timescale------------------------------//
`timescale 1 ns / 1 ps
//--------------------Module_TXD_RXD_Ctrl-----------------------//
	module TXD_RXD_Ctrl(
						input rst_n,
						input BPS_CLK,
						input RX,
						output TX,
						output FPGA_LEDR,FPGA_LEDG,FPGA_LEDB,
						output A,_A,B,_B
						);

//---------------------------parameter--------------------------------//
	parameter ledr = 40'b01001100_01000101_01000100_01010010_00001010,
				 ledg = 40'b01001100_01000101_01000100_01000111_00001010,
				 ledb = 40'b01001100_01000101_01000100_01000010_00001010,
				 forw = 40'b01000110_01001111_01010010_01010111_00001010,
				 back = 40'b01000010_01000001_01000011_01001011_00001010,
				 stop = 40'b01010011_01010100_01001111_01010000_00001010,
				 go = 16'b01000111_01001111,
				 atEnd = 8'b00001010;
//---------------------------RXD--------------------------------//
	/* 接收模块 */
	reg[3:0]j;
	reg[7:0]data_in;
	reg [47:0]receive_data;
	reg [39:0]data_inr;
	reg [39:0] compare;
	reg [3:0] pp;
	reg [23:0] SUM;

	always@(posedge BPS_CLK or negedge rst_n)
		if(!rst_n)
			begin
				j <= 4'd0;
				data_in <= 8'd0;
				data_inr <= 40'd0;
				receive_data <= 48'd0;
			end
		else case(j)
				4'd0:                                    				//判断起始标志
					begin
						if(!RX)//无信号为1      
							begin
								data_in <= 8'd0;
								j <= j+ 1'd1;
							end
						else j <= j;
					end
				4'd1,4'd2,4'd3,4'd4,4'd5,4'd6,4'd7,4'd8:				//接收数据
					begin
						j <= j + 1'd1;
						data_in <= {RX,data_in[7:1]};
					end
				4'd9:                                   				//接收校验位
					begin
						receive_data <= {receive_data[39:0],data_in};
						j <= j + 1'd1;
					end
				4'd10: 															//接收停止位
					begin
						j <= 1'd0;
						if(receive_data[7:0] == 8'b00001010)
							begin
								data_inr <= {receive_data[47:16],atEnd};
								//compare <= {data_inr[47:16],atEnd};//非阻塞赋值
								pp <= receive_data[11:8];
								delayTime <= receive_data[11:8];
								SUM <= receive_data[31:8];
							end
					end
				default: j <= 4'd0;
		endcase	
		
//---------------------------步进电机---------------------------//
	
	reg [2:0] step;
	reg [3:0] moto;
	reg [3:0] delay = 6'b0;
	assign {A,_A,B,_B} = moto;
	localparam step1=3'b000,step2=3'b001,step3=3'b010,step4=3'b011,step5=3'b100,step6=3'b101,step7=3'b110,step8=3'b111;
	reg [3:0] delayTime = 4'b0100;
	reg true = 1'b1;
	reg GO = 1'b0;
	reg goModule = 1'b0;
	reg [15:0] pulseCount = 80'b0;
	
	always@(posedge BPS_CLK or negedge rst_n)
		begin
			if(!rst_n)
				begin
					moto <= 4'b1111;
					step <= step1;
					delay <= 12'd0;
				end
			else
				begin
					if(delay < delayTime)
						begin
							delay <= delay + 1'b1;
						end
					else if(GO)
						begin
							delay <= 6'd0;
							case (step)
								step1:begin
											moto <= 4'b1000;
											if(true) step <= step2;
											else step <= step8;
										end
								step2:begin
											moto <= 4'b1010;
											if(true) step <= step3;
											else step <= step1;
										end
								step3:begin
											moto <= 4'b0010;
											if(true) step <= step4;
											else step <= step2;
										end
								step4:begin
											moto <= 4'b0110;
											if(true) step <= step5;
											else step <= step3;
										end
								step5:begin
											moto <= 4'b0100;
											if(true) step <= step6;
											else step <= step4;
										end
								step6:begin
											moto <= 4'b0101;
											if(true) step <= step7;
											else step <= step5;
										end
								step7:begin
											moto <= 4'b0001;
											if(true) step <= step8;
											else step <= step6;
										end
								step8:begin
											moto <= 4'b1001;
											if(true) step <= step1;
											else step <= step7;
										end
								default:step <= step1;
							endcase
						end
				end
		end
		
	
//---------------------------LED--------------------------------//	
	/*对比接收数据 */
	reg [2:0]led;		
	reg countModule = 1'b0;
	reg calculation[7:0];
	always@(posedge BPS_CLK or negedge rst_n)
		begin
				if(!rst_n)
					begin
						led <= 3'b111;
					end
				else if (data_inr == ledr)                  
						led <= 3'b011;
				else if (data_inr == ledg)
						led <= 3'b101;
				else if (data_inr == ledb)
						led <= 3'b110;	
				else if (data_inr == forw)
						begin
							GO <= 1'b1;
							true <= 1'b1;
							countModule <= 1'b0;
						end
				else if (data_inr == back)
						begin
							GO <= 1'b1;
							true <= 1'b0;
							countModule <= 1'b0;
						end
				else if (data_inr == stop)
						begin
							GO <= 1'b0;
							countModule <= 1'b0;
						end
				else if (data_inr[39:24] == go)
						begin
							calculation <= SUM[23:16]<<6 + SUM[15:8] + SUM[7:0];
							countModule <= 1'b1;
							if(countModule)
								begin
											if(pulseCount >= calculation)
												begin
													GO <= 1'b0;
													//pulseCount <= 16'b0;
												end
											else
												begin
													GO <= 1'b1;
													pulseCount <= pulseCount + 1'b1;
												end
								end
						end
				else
						begin
							led <= 3'b111;
						end
		end
			
	reg[2:0] temp;
	assign {FPGA_LEDR,FPGA_LEDG,FPGA_LEDB} = temp;
	
//-------------------------尝试呼吸------------------------------//

	parameter Tls = 14'd9600;
	reg[13:0] count;
	reg[3:0] count1;
	reg[1:0] state;
	localparam 
	s0=2'b00,s1=2'b01,s2=2'b10;

	always @ (posedge BPS_CLK or negedge rst_n)
		begin
			if(!rst_n)
				begin
					count <= 0;
					count1 <= 0;
					state <= s0;
					temp <= 3'b101;
				end
			else
				begin
					case (state)
					s0:begin
						if(!RX)//无信号为1        
							begin
								count <= 0;
								count1 <= 0;
								state <= s1;
							end
						else state <= s0;
						end
					s1: begin
							if(count1 < pp)
								begin
									if(count < Tls - 1)
										begin
											count <= count+1'd1;
											temp <= led;
											state <= s1;
										end
									else
										begin
											count <= 0;
											count1 <= count1 + 1'b1;
										end
								end
							else
								begin
									count <= 0;
									state <= s2;
									count1 <= 0;
								end
						 end
					s2: begin
							if(count1 < pp)
								begin
									if(count < Tls - 1)
										begin
											count <= count+1'd1;
											temp <= 3'b111;
											state <= s2;
										end
									else
										begin
											count <= 0;
											count1 <= count1 + 1'b1;
										end
								end
							else
								begin
									count <= 0;
									state <= s1;
									count1 <= 0;
								end
						end
					default: state <= s0;
					endcase
				end
	end

//--------------------TXD---------------------------------------//
	/*发送模块，定时发送GINGKO*/
	reg TX_r; 																				//串行发送数据的寄存器,空闲状态默认为1
	reg[13:0]i;
	reg[7:0]data_out;
	reg[3:0]cnt;
	reg[63:0]GINGKO;
	
	always @(posedge BPS_CLK or negedge rst_n)
		if (!rst_n)
			begin
				i <= 14'd0;
				TX_r <= 1'd1;																 //空闲状态为1
				cnt <= 4'd0;
				data_out <= 8'd0;
				GINGKO <= {8'd71,8'd73,8'd78,8'd71,8'd75,8'd79,8'd13,8'd10};
			end
		else 																					 //开始发送DATA
			case(i)
				14'd0: begin																 //先发送起始位0
							i <= i + 1'd1;
							{data_out,GINGKO[63:8]} <= GINGKO;
							TX_r <= 1'd0;													
						end
				14'd1,14'd2,14'd3,14'd4,14'd5,14'd6,14'd7,14'd8:				 //TX_r将DATA数据发送出去
						begin
							i <= i + 1'd1;
							{data_out[6:0],TX_r} <= data_out; 						 //串口发送时,低位在先
						end								
				14'd9: begin																 //1位奇偶校验位和1位停止位
							i <= i + 1'd1;
							TX_r <= 1'd1;                                      
						end
				14'd10: begin																 //1位停止位
							if(cnt == 4'd7)
								begin
									i <= i + 1'd1;
									cnt <= 4'd0;
								end
							else 
								begin
									i <= 14'd0;
									cnt <= cnt + 1'd1;
								end
						end
				14'd9600: begin															//定时约为1s				
								i <= 14'd0;
								GINGKO <= {8'd71,8'd73,8'd78,8'd71,8'd75,8'd79,8'd13,8'd10};
						end
				default: i <= i + 1'd1;  												//i为其他无效数值时,直接转到退出TXD模块状态
			endcase

	assign TX = TX_r;	
//--------------------Endmodule---------------------------------//
	endmodule
